package com.ljc.utils;

import com.google.gson.Gson;
import com.ljc.constant.RabbitMqConstant;
import com.ljc.constant.RedisConstant;
import com.ljc.model.entity.InterfaceInfo;
import com.ljc.service.InterfaceInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * 向mq发送消息，保证接口信息的可靠性处理
 */
@Slf4j
@Component
public class InterfaceRabbitMqUtils {

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private InterfaceInfoService interfaceInfoService;
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 更新缓存
     */
    public void operateInterfaceInfo(Long interfaceInfoId, int operate) {
        InterfaceInfo interfaceInfo = interfaceInfoService.getById(interfaceInfoId);
        String messageId = UUID.randomUUID().toString();
        switch (operate) {
            case 1:
                try {
                    // 发送消息之前，先记录创建重试次数
                    stringRedisTemplate.opsForValue().set(RedisConstant.INTERFACE_RETRY_PREFIX + messageId, "0");
                    rabbitTemplate.convertAndSend(RabbitMqConstant.INTERFACE_EXCHANGE_NAME,
                            RabbitMqConstant.INTERFACE_DELETE_EXCHANGE_ROUTING_KEY, new Gson().toJson(interfaceInfo), message -> {
                                MessageProperties messageProperties = message.getMessageProperties();
                                //生成全局唯一id
                                messageProperties.setMessageId(messageId);
                                messageProperties.setConsumerTag("删除信息");
                                messageProperties.setContentEncoding("utf-8");
                                return message;
                            });
                } catch (AmqpException e) {
                    log.error("发送接口操作消息失败，接口id{}", interfaceInfo);
                    // 删除在Redis中记录的重试次数
                    stringRedisTemplate.delete(RedisConstant.INTERFACE_RETRY_PREFIX + messageId);
                    throw new RuntimeException(e);
                }
                break;
            case 2:
                // 发送消息之前，先记录创建重试次数
                try {
                    stringRedisTemplate.opsForValue().set(RedisConstant.INTERFACE_RETRY_PREFIX + messageId, "0");
                    rabbitTemplate.convertAndSend(RabbitMqConstant.INTERFACE_EXCHANGE_NAME,
                            RabbitMqConstant.INTERFACE_UPDATE_EXCHANGE_ROUTING_KEY, new Gson().toJson(interfaceInfo), message -> {
                                MessageProperties messageProperties = message.getMessageProperties();
                                //生成全局唯一id
                                messageProperties.setMessageId(messageId);
                                messageProperties.setConsumerTag("更新/新增接口信息");
                                messageProperties.setContentEncoding("utf-8");
                                return message;
                            });
                } catch (AmqpException e) {
                    log.error("发送接口操作消息失败，接口id{}", interfaceInfoId);
                    // 删除在Redis中记录的重试次数
                    stringRedisTemplate.delete(RedisConstant.INTERFACE_RETRY_PREFIX + messageId);
                    throw new RuntimeException(e);
                }
                break;
        }
    }

    /*    *//**
     * 交换机确认回调方法
     * 1、发消息 交换机接收到了 回调
     *  1.1、correlationData 保存回调消息的ID及相关信息
     *  1.2、交换机收到消息 ack = true
     *  1.3、cause null
     * 2、发消息 交换机接收失败了 回调
     *  2.1、correlationData 保存回调消息的ID及相关信息
     *  2.2、交换机收到消息 ack = false
     *  2.3、cause 失败原因
     * @param correlationData correlation data for the callback.
     * @param ack true for ack, false for nack
     * @param cause An optional cause, for nack, when available, otherwise null.
     *//*
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        // 交换机收到消息
        if (ack){
            log.info("交换机收到消息");
        } else {
            // 交换机未收到消息
            log.error("交换机未收到消息");
        }
    }

    *//**
     * 队列确认回调方法
     * 只有不可达队列的时候才进行回退
     * @param returned the returned message and metadata.
     *//*
    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.error("消息发送到队列异常，返回消息回调:{}", returned);
    }

    // 将自身注入到confirmCallback接口中
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnsCallback(this);
    }*/
}
